﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Phoenix.Xna.Framework.Input.Keyboards
{
    /// <summary>
    /// Manages keyboards connected to the system.  This manager is a singleton.
    /// </summary>
    internal sealed class KeyboardManager : HumanInterfaceDevice
    {
        private class NestedSingleton
        {
            internal static readonly KeyboardManager Singleton = new KeyboardManager();

            static NestedSingleton() { }
        }

        /// <summary>
        /// Gets a singleton instance of the KeyboardManager.
        /// </summary>
        public static KeyboardManager Instance
        {
            get { return NestedSingleton.Singleton; }
        }

        private KeyboardManager()
            : base()
        {
            Type = DeviceType.Keyboard;
            ValidTypes.Add(typeof(KeyboardKeyMap));
            KeyboardStateManager.Instance.StateChanged += new EventHandler(OnStateChanged);
            KeyboardStateManager.Instance.Update();
        }

        /// <summary>
        /// Finds a KeyMap in the internal collection that contains the specified keys.
        /// </summary>
        /// <param name="keys">The keys contained in the KeyMap to find.</param>
        /// <returns>The KeyMap that matches the specified keys, otherwise null.</returns>
        public KeyboardKeyMap FindMap(List<Keys> keys)
        {
            foreach (KeyboardKeyMap m in InputMaps)
            {
                if (m.MappedKeys == keys)
                {
                    return m;
                }
            }

            return null;
        }

        #region IHumanInterfaceDevice Members

        /// <summary>
        /// Updates the interface device.
        /// </summary>
        /// <param name="gameTime">A snapshot of the elapsed game time.</param>
        public override void Update(GameTime gameTime)
        {
            KeyboardStateManager.Instance.Update();
            base.Update(gameTime);
        }

        #endregion
    }
}
